#ifndef GENETICSENGINE_H
#define GENETICSENGINE_H

#include <vector>

class Entity;
class Track;
struct Genome;

class GeneticsEngine
{
public:
	GeneticsEngine();
	~GeneticsEngine();

	bool Init(Track* a_pTrack);
	void RunCycle(float a_dt);

	//Functionality
	void RunRace();
	void Pause(bool a_pause);
	void Reset();
	void UpdateGUI();
	void EnableDebugOutput(bool a_output);

	//Gets
	float GetMutationRate() const;
	float GetMaxChildren() const;
	float GetCarSpeed() const;
	float GetOffTrackPenalty() const;
	Entity* GetFather() const;
	Entity* GetMother() const;
	bool IsPaused() const;

  Track* GetTrack();

	//Sets
	void SetMaxChildren(int a_max);
	void SetCarSpeed(float a_speed);
	void SetOffTrackPenalty(float a_penalty);
	void SetEvolutionsPer(int a_number);
	void SetTimeout(float a_timeout);
	void ApplyMutations(Genome* a_pGenome);
	void ApplyWeights(float a_weight1, float a_weight2);

private:
	
	//Should only ever be called by the engine
	void EndCycle();
	void GenerateParents();
	void MutateAll(std::vector<Genome> a_mutatedGenes);
	void Mutate(Entity& a_entity, std::vector<Genome> a_genome, float a_mutationRate);
	std::vector<Genome> Merge(Entity* a_pLhs, Entity* a_pRhs);
	Track* m_pTrack;

	//m_playbackMode;

	float m_mutationRate;
	int m_maxChildren;
	float m_maxCarSpeed;
	float m_offTrackPenalty;
	int m_numEvolutions;
	int m_evolutionsPerRender;
	float m_timeout;

	float m_fastestLap;
	float m_averageLap;
	float m_slowestLap;

	bool m_isPaused;
	bool m_debugOutput;

	float m_count;

	std::vector<Entity*> m_entities;

	//Parent entities
	Entity* m_pFather;
	Entity* m_pMother;

	float m_fatherWeight;
	float m_motherWeight;

	int m_numGenes;
};

#endif //GENETICSENGINE_H